<?php

namespace app\service;


use app\model\WorkTimeRecordModel;
use app\tool\SingletonTrait;
use support\Request;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class WorkTimeService
{
    use SingletonTrait;

    public function __construct()
    {
    }

    /**
     * 租户成员工时time log修正统计
     * @param int $tenantId
     * @param array $projectIdList
     * @param $startTime
     * @param $endTime
     * @param $departmentId
     * @param $roleCode
     * @param array $userId
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getTenantUserStatistics(int $tenantId, array $projectIdList, $startTime, $endTime, $departmentId, $roleCode, array $userId): array
    {
        $roleCodes = [];
        $departmentIds = [];
        $res = [];
        if (!empty($departmentId) || !empty($roleCode)) {
            if (!empty($departmentId)) {
                if (is_array($departmentId)) {
                    $departmentIds = $departmentId;
                } else {
                    $departmentIds[] = $departmentId;
                }
            }
            if (!empty($roleCode)) {
                $roleCodes[] = $roleCode;
            }
        } else {
            // 查询当前所属当前租户的所有部门
            $departmentListQueryRes = DepartmentService::getInstance()->getDepartmentList($tenantId, null);
            if (empty($departmentListQueryRes)) {
                return [];
            }
            // 部门 ids
            foreach ($departmentListQueryRes as $departmentItem) {
                $res[] = [
                    'id' => intval($departmentItem['id']),
                    'name' => $departmentItem['name'],
                    'type' => 'department',
                    'parent_id' => $departmentItem['parent_id'],
                    'work_hour' => 0,
                    'task_work_hour' => 0,
                    'im_user_id' => 0
                ];
                $departmentIds[] = $departmentItem['id'];
            }
        }

        $query = (new \app\model\WorkTimeRecordModel)->field('sum(work_time) AS work_time,user_id');
        if (!empty($projectIdList)) {
            $query->whereIn('project_id', $projectIdList);
        }
        if (!empty($startTime)) {
            $query->whereFieldRaw('record_time', '>=', strtotime($startTime));
        }
        if (!empty($endTime)) {
            $query->whereFieldRaw('record_time', '<=', strtotime($endTime));
        }
        $userWorkTimeRes = $query->group('user_id')->select();
        if (empty($userWorkTimeRes->toArray())) {
            return [];
        }
        $userWorkTimeResMap = array_column($userWorkTimeRes->toArray(), null, 'user_id');

        // 获取部门下的用户
        // 获取指定租户下面所有用户及其角色标签
        if (!empty($departmentId) || !empty($roleCode)) {
            $userList = [];
            if (!empty($departmentId)) {
                $userList = UserService::getInstance()->byDepartmentOrRoleSelectUser($departmentIds, $roleCodes, [], $userId);
                if (empty($userList)) {
                    return [];
                }
            }
            if (!empty($roleCode)) {
                $userList = UserService::getInstance()->byDepartmentOrRoleSelectUser([], $roleCodes, [$tenantId], $userId);
                if (empty($userList)) {
                    return [];
                }
            }
            $imUserIdList = [];
            foreach ($userList as $userItem) {
                $imUserIdList[] = $userItem['union_id'];
            }

            $workHourMap = $this->queryUserWorkHour($imUserIdList, $startTime, $endTime);
            if (empty($workHourMap)) {
                return [];
            }
            foreach ($userList as $userItem) {
                $tmpWorkTime = 0;
                $tmpWorkHour = 0.00;
                if (!empty($userWorkTimeResMap[$userItem['id']])) {
                    $tmpWorkTime = $userWorkTimeResMap[$userItem['id']]['work_time'];
                }
                if (!empty($workHourMap[$userItem['union_id']])) {
                    $tmpWorkHour = $workHourMap[$userItem['union_id']];
                }
                $res[] = [
                    'id' => intval($userItem['id']),
                    'name' => $userItem['name'],
                    'type' => 'user',
                    'parent_id' => 0,
                    'work_hour' => $tmpWorkHour,
                    'task_work_hour' => round(floatval($tmpWorkTime) / 3600, 2),
                    'im_user_id' => intval($userItem['union_id'])
                ];
            }
        } else {
            $getDepartmentUserMultiDepartmentUserData = UserService::getInstance()->getDepartmentUserMultiDepartmentUser($departmentIds, $tenantId);
            if (empty($getDepartmentUserMultiDepartmentUserData)) {
                return [];
            }
            $departmentUsers = $getDepartmentUserMultiDepartmentUserData['department_users'];
            $distinctUserIds = $getDepartmentUserMultiDepartmentUserData['distinct_user_ids'];
            $imUserIdList = UserService::getInstance()->getUnionIdListByUserIdList($distinctUserIds);
            if (empty($imUserIdList)) {
                return [];
            }
            $workHourMap = $this->queryUserWorkHour($imUserIdList, $startTime, $endTime);
            if (empty($workHourMap)) {
                return [];
            }
            foreach ($departmentUsers as $departmentUserItem) {
                $tmpWorkTime = 0;
                $tmpWorkHour = 0.00;
                if (!empty($userWorkTimeResMap[$departmentUserItem['user_id']])) {
                    $tmpWorkTime = $userWorkTimeResMap[$departmentUserItem['user_id']]['work_time'];
                }
                if (!empty($workHourMap[$departmentUserItem['union_id']])) {
                    $tmpWorkHour = $workHourMap[$departmentUserItem['union_id']];
                }
                $res[] = [
                    'id' => intval($departmentUserItem['user_id']),
                    'name' => $departmentUserItem['user_name'],
                    'type' => 'user',
                    'parent_id' => $departmentUserItem['department_id'],
                    'work_hour' => $tmpWorkHour,
                    'task_work_hour' => round(floatval($tmpWorkTime) / 3600, 2),
                    'im_user_id' => 0,
                ];
            }
        }

        return $res;
    }

    /**
     * 查询用户上班打卡工时
     * @param $userIdList
     * @param $startTime
     * @param $endTime
     * @return array
     */
    public function queryUserWorkHour($userIdList, $startTime, $endTime): array
    {
        $userInfo = teamones_request('teamones-work-hour', 'dingtalk/get_user_work_times', [
            'user_id_list' => $userIdList,
            'work_date_from' => date('Y-m-d 00:00:00', strtotime($startTime)),
            'work_date_to' => date('Y-m-d 00:00:00', strtotime($endTime)),
        ]);
        if (empty($userInfo['data'])) {
            return [];
        }
        $res = [];
        foreach ($userInfo['data'] as $item) {
            $res[$item['user_id']] = $item['work_hour'];
        }
        return $res;
    }

    /**
     * 导出工时报表
     * @param Request $request
     * @param array $projectIdList
     * @param string $dateStart
     * @param string $dateEnd
     * @param array $page
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function exportStatistics(Request $request, array $projectIdList, string $dateStart, string $dateEnd, array $page): array
    {
        $res = [];
        $dbr = WorkTimeRecordModel::where('work_time_record.tenant_id', $request->getTenantId());
        if (!empty($projectIdList)) {
            $dbr = $dbr->whereIn('work_time_record.project_id', $projectIdList);
        }

        // Todo 检查时区
        if (!empty($dateStart)) {
            $timeStart = strtotime(date('Y-m-d', strtotime($dateStart)));
            $dbr = $dbr->where('work_time_record.record_time', '>=', $timeStart);
        }
        if (!empty($dateEnd)) {
            $timeEnd = strtotime(date('Y-m-d', strtotime($dateEnd)));
            $dbr = $dbr->where('work_time_record.record_time', '<=', $timeEnd);
        }
        $dbr = $dbr->field('user_id, sum(work_time) as work_time')
            ->group('user_id');

        // 获取所有用户
        $userList = UserService::getInstance()->getUserListPage('id > 1143', $page);
        $distinctUserIds = array_unique(array_column($userList, 'id'));

        $userWorkTimeRes = $dbr
            ->whereIn('user_id', $distinctUserIds)
            ->select()->toArray();
//        $userIdList = array_column($userWorkTimeRes, 'user_id');
        $userWorkTimeResMap = array_column($userWorkTimeRes, null, 'user_id');

        $imUserIdList = UserService::getInstance()->getUnionIdListByUserIdList($distinctUserIds);
        $workHourMap = WorkHourService::getInstance()->queryUserWorkHour($imUserIdList, $dateStart . ' 00:00:00', $dateEnd . ' 00:00:00');

        foreach ($userList as $user) {
            $res[] = [
                'id' => intval($user['id']),
                'name' => $user['name'],
                'work_hour' => $workHourMap[$user['union_id']] ?? 0,
                'task_work_hour' => doubleval($userWorkTimeResMap[$user['id']]['work_time'] ?? 0) / 3600,
            ];
        }
        return result_array_construct([
            'id' => 'intval',
            'name' => 'strval',
            'work_hour' => 'sprintf,%.2f|doubleval',
            'task_work_hour' => 'sprintf,%.2f|doubleval',
        ], $res);
    }

    /**
     * 查询用户填写的工时汇总
     * @param $param
     * @param $getTenantId
     * @return array|string[]
     */
    public function getUserWorkTimes($param, $getTenantId)
    {
        $workDateFrom = strtotime($param['work_date_from']);
        $workDateTo = strtotime($param['work_date_to']);
        $userIdList = $param['user_id_list'];
        $data = WorkTimeRecordModel::alias('w')
            ->join("user u", 'u.id = w.user_id')
            ->whereIn("u.union_id", $userIdList)
            ->whereBetween('w.record_time', [$workDateFrom, $workDateTo])
            ->field('u.union_id user_id,w.record_time,concat(u.union_id,"#",w.record_time) uk,sum(work_time) second')
            ->group('u.union_id,w.record_time')
            ->order('u.union_id,w.record_time')
            ->select();
        $data = $data->column('second', 'uk');
        $dateArr = [];
        for ($start = $workDateFrom; $start <= $workDateTo; $start += (24 * 3600)) {
            echo date("Y-m-d H:i:s", $start) . PHP_EOL;
            $dateArr[] = $start;
        }
        $res = [];
        foreach ($userIdList as $userId) {
            $userHourList = [];
            $workHourMinutes = 0;
            foreach ($dateArr as $dateTimeStamp) {
                $uk = "$userId#$dateTimeStamp";
                $daySecond = $data[$uk] ?? 0;
                $userHourList[$dateTimeStamp] = round($daySecond / 60, 2);
                $workHourMinutes += $userHourList[$dateTimeStamp];
            }
            $res[] = [
                'user_id' => $userId,
                'work_hour' => round($workHourMinutes / 60, 2),
                'work_every_day_min' => $userHourList
            ];
        }
        return $res;
    }
}
